package org.shagin.jfin.core.ui;

import java.awt.Component;
import java.awt.Container;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JSplitPane;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UIManager.LookAndFeelInfo;
import javax.swing.plaf.basic.BasicSplitPaneDivider;
import javax.swing.plaf.basic.BasicSplitPaneUI;

/**
 * The Class UIUtils.
 */
public class UIUtils {

    public static final int DEFAULT_DEFFERED_ACTION_DELAY = 500;
    public static final String NimbusLAF = "Nimbus";
    public static final String WindowsLAF = "Windows";
    public static final String DefaultLAF = WindowsLAF;

    /**
     * Center screen.
     * 
     * @param component the component
     */
    public static void centerScreen(Container component) {
        Toolkit toolkit = component.getToolkit();
        Dimension s = toolkit.getScreenSize();
        Point p = new Point();
        p.x = (s.width / 2) - (component.getWidth() / 2);
        p.y = (s.height / 2) - (component.getHeight() / 2);
        component.setLocation(p);
    }

    /**
     * Center container.
     * 
     * @param parent the parent
     * @param component the component
     */
    public static void centerContainer(Container parent, Container component) {
        if (parent == null) {
            centerScreen(component);
        } else {
            Rectangle rect = parent.getBounds();
            Point p = new Point();
            p.x = rect.x + (rect.width / 2) - (component.getWidth() / 2);
            p.y = rect.y + (rect.height / 2) - (component.getHeight() / 2);
            component.setLocation(p);
        }
    }

    /**
     * Resize container.
     * 
     * @param parent the parent
     * @param component the component
     * @param dx the dx
     * @param dy the dy
     */
    public static void resizeContainer(Container parent, Container component,
            double dx, double dy) {
        if (parent != null) {
            Dimension d = parent.getSize();
            d.width = Long.valueOf(Math.round(d.width * dy)).intValue();
            d.height = Long.valueOf(Math.round(d.height * dy)).intValue();
            component.setSize(d);
        }
    }

    /**
     * Resize and center container.
     * 
     * @param parent the parent
     * @param component the component
     * @param dx the dx
     * @param dy the dy
     */
    public static void resizeAndCenterContainer(Container parent,
            Container component, double dx, double dy) {
        resizeContainer(parent, component, dx, dy);
        centerContainer(parent, component);
    }

    /**
     * Sets the width percent.
     * 
     * @param parent the parent
     * @param component the component
     * @param proportionalWidth the proportional width
     */
    public static void setWidthPercent(Container parent, Container component,
            double proportionalWidth) {
        Dimension p = parent.getSize();
        Dimension d = component.getSize();
        d.width = Long.valueOf(
                Math.round(p.getSize().width * proportionalWidth)).intValue();
        component.setSize(d);
        component.setPreferredSize(d);
    }

    /**
     * Display the egg timer cursor when the frame has focus. Just left in for
     * patch (will break existing classes otherwise)
     * 
     * @param frame the new wait cursor
     */
    public static void setWaitCursor(JFrame frame) {
        frame.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
    }

    /**
     * Display the egg timer cursor when the frame has focus.
     * 
     * @param window the new wait cursor
     */
    public static void setWaitCursor(Window window) {
        window.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
    }

    /**
     * Display the default cursor when the frame has focusJust left in for patch
     * (will break existing classes otherwise).
     * 
     * @param frame the new default cursor
     */
    public static void setDefaultCursor(JFrame frame) {
        frame.setCursor(Cursor.getDefaultCursor());
    }

    /**
     * Display the default cursor when the frame has focus.
     * 
     * @param window the new default cursor
     */
    public static void setDefaultCursor(Window window) {
        window.setCursor(Cursor.getDefaultCursor());
    }

    /**
     * Set native look and feel.
     */
    public static void setNativeLF() {
        try {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        } catch (Exception ignore) {
        }
    }

    /**
     * Sets the default la f.
     */
    public static void setDefaultLaF() {
        try {
            for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
                if (DefaultLAF.equals(info.getName())) {
                    UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * Retrieve the frame that the passed component resides in.
     * 
     * @param component the component
     * @return the containing frame
     */
    public static JFrame getContainingFrame(Component component) {
        // Recurse up the tree
        JFrame container = null;
        Component candidate = component;
        while (candidate != null && container == null) {
            // Grab the next parent from the hierarchy
            candidate = candidate.getParent();
            if (candidate instanceof JFrame)
                container = (JFrame) candidate;
        }
        return container;
    }

    /**
     * Retrieve the dialog that the passed component resides in.
     * 
     * @param component the component
     * @return the containing dialog
     */
    public static JDialog getContainingDialog(Component component) {
        // Recurse up the tree
        JDialog container = null;
        Component candidate = component;
        while (candidate != null && container == null) {
            // Grab the next parent from the hierarchy
            candidate = candidate.getParent();
            if (candidate instanceof JDialog)
                container = (JDialog) candidate;
        }
        return container;
    }

    /**
     * Sets the enabled.
     * 
     * @param component the component
     * @param enabled the enabled
     */
    public static void setEnabled(JComponent component, boolean enabled) {
        // enable/disable this component
        component.setEnabled(enabled);

        // Recurse through children
        Component[] children = component.getComponents();
        for (int i = 0; i < children.length; i++)
            if (children[i] instanceof JComponent)
                setEnabled((JComponent) children[i], enabled);
    }

    /**
     * Creates the split pane without borders.
     * 
     * @param orientation the orientation
     * @param dividerSize the divider size
     * @return the j split pane
     */
    public static JSplitPane createSplitPane(int orientation, int dividerSize) {
        JSplitPane split = new JSplitPane(orientation);
        // remove the border from the split pane
        split.setBorder(null);

        // set the divider size for a more reasonable, less bulky look
        split.setDividerSize(dividerSize);

        // check the UI. If we can't work with the UI any further, then
        // exit here.
        if (!(split.getUI() instanceof BasicSplitPaneUI))
            return split;

        // grab the divider from the UI and remove the border from it
        BasicSplitPaneDivider divider = ((BasicSplitPaneUI) split.getUI())
                .getDivider();
        if (divider != null)
            divider.setBorder(null);

        return split;
    }

    /**
     * Run deffred action.
     * 
     * @param action the action
     */
    public static void runDeffredAction(final Runnable action) {
        Timer timer = new Timer(DEFAULT_DEFFERED_ACTION_DELAY,
                new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        if (action != null)
                            action.run();
                    }
                });
        timer.setRepeats(false);
        timer.start();
    }

}
